<?php

declare (strict_types=1);

namespace app\timer\service\dealer;

use app\common\library\helper;
use app\timer\library\Tools;
use app\timer\model\dealer\User as DealerUserModel;
use app\timer\model\dealer\Order as DealerOrderModel;
use app\common\service\BaseService;
use think\model\Collection;

/**
 * 服务类：分销订单模块
 * Class Order
 * @package app\timer\service\dealer
 */
class Order extends BaseService
{
    /**
     * 标记失效的分销订单
     * @param int $storeId
     * @return bool
     */
    public function invalidEvent(int $storeId): bool
    {
        // 获取已失效的订单ID集
        $model = new DealerOrderModel;
        $invalidOrderIds = $model->getInvalidOrderIds($storeId);
        // 记录日志
        Tools::taskLogs('DealerOrder', 'invalidEvent', [
            'storeId' => $storeId,
            'invalidOrderIds' => helper::jsonEncode($invalidOrderIds)
        ]);
        // 标记订单失效状态
        return empty($invalidOrderIds) || $model->setInvalid($invalidOrderIds);
    }

    /**
     * 分销佣金结算（已完成订单）
     * @param int $storeId
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function grantMoneyEvent(int $storeId)
    {
        // 获取未结算的分销订单
        $model = new DealerOrderModel;
        $orderList = $model->getUnSettledList($storeId);
        // 发放分销订单佣金
        $this->settlement($storeId, $orderList);
        // 记录日志
        Tools::taskLogs('DealerOrder', 'grantMoneyEvent', [
            'storeId' => $storeId,
            'ids' => helper::jsonEncode(helper::getArrayColumn($orderList, 'id')),
            'orderIds' => helper::jsonEncode(helper::getArrayColumn($orderList, 'order_id'))
        ]);
    }

    /**
     * 发放分销订单佣金(批量)
     * @param int $storeId
     * @param Collection $orderList
     */
    public function settlement(int $storeId, Collection $orderList)
    {
        $model = new DealerOrderModel;
        $model->transaction(function () use ($storeId, $orderList) {
            foreach ($orderList as $order) {
                static::grantMoneyOrder($storeId, $order);
            }
        });
    }

    /**
     * 发放分销订单佣金(单独)
     * @param int $storeId
     * @param DealerOrderModel $orderItem 分销订单详情
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    private static function grantMoneyOrder(int $storeId, DealerOrderModel $orderItem): void
    {
        // 判断存在未处理的售后退款, 则不进行分佣
        if (static::checkExistRefunding($orderItem)) {
            return;
        }
        // 重新计算分销佣金
        $capital = DealerOrderModel::getCapitalByOrder($orderItem['order']);
        // 发放一级分销商佣金
        $orderItem['first_user_id'] > 0 && DealerUserModel::grantMoney((int)$orderItem['first_user_id'], (float)$capital['first_money'], $storeId);
        // 发放二级分销商佣金
        $orderItem['second_user_id'] > 0 && DealerUserModel::grantMoney((int)$orderItem['second_user_id'], (float)$capital['second_money'], $storeId);
        // 发放三级分销商佣金
        $orderItem['third_user_id'] > 0 && DealerUserModel::grantMoney((int)$orderItem['third_user_id'], (float)$capital['third_money'], $storeId);
        // 更新分销订单记录
        $orderItem->save([
            'order_price' => $capital['orderPrice'],
            'first_money' => $capital['first_money'],
            'second_money' => $capital['second_money'],
            'third_money' => $capital['third_money'],
            'is_settled' => 1,
            'settle_time' => time()
        ]);
    }

    /**
     * 验证商品是否存在售后退款(进行中)
     * @param DealerOrderModel $orderItem
     * @return bool
     */
    private static function checkExistRefunding(DealerOrderModel $orderItem): bool
    {
        foreach ($orderItem['order']['goods'] as $item) {
            if (DealerOrderModel::checkExistRefunding($item)) {
                return true;
            }
        }
        return false;
    }
}